#include "riscv-plic.h"
#include "riscv-csr.h"
#include "riscv-it.h"
#include "uart.h"
#include "reg_common.h"

void interrupt_plic_test(void) {
	uint32_t val;

    printf("Interrupt test start!!\r\n");
    printf("--------------------------------------------------------------------------------------------------------------\r\n");

	asm volatile ("li t3, 0x100 \n\t");
	asm volatile ("csrw pmpaddr8, t3 \n\t");
	asm volatile ("li t3, 0x88 \n\t");
	asm volatile ("csrw pmpcfg2, t3 \n\t");

    // DBG_LSB_REG = 0x1;      // WDT - 0
    // DBG_LSB_REG = 0x2;      // GP Timer - 1
    // DBG_LSB_REG = 0x4;      // Boot SPI - 2
    DBG_LSB_REG = 0x8;      // GP SPI - 3
    DBG_LSB_REG = 0x10;     // Mailbox - 4
    //DBG_LSB_REG = 0x20;     // UART - 5
    DBG_LSB_REG = 0x40;     // I2C - 6
    DBG_LSB_REG = 0x80;     // GBE0 - 7
    DBG_LSB_REG = 0x100;    // GBE1 - 8
    DBG_LSB_REG = 0x200;    // USB0 - 9
    DBG_LSB_REG = 0x400;    // USB1 - 10
    DBG_LSB_REG = 0x800;    // Rsevd0 - 11
    DBG_LSB_REG = 0x1000;   // Resvd1 - 12
    DBG_LSB_REG = 0x2000;   // Resvd2 - 13
    DBG_LSB_REG = 0x4000;   // Resvd3 - 14
    DBG_LSB_REG = 0x8000;   // Resvd4 - 15
    DBG_LSB_REG = 0x10000;  // DDR0 - 16
    DBG_LSB_REG = 0x20000;  // DDR1 - 17
    DBG_LSB_REG = 0x40000;  // PCIe0 - 18
    DBG_LSB_REG = 0x80000;  // PCIe1 - 19
    DBG_LSB_REG = 0x100000;  // PCIe2 - 20
    DBG_LSB_REG = 0x200000;  // PCIe3 - 21
    DBG_LSB_REG = 0x400000;  // PCIe4 - 22
    DBG_LSB_REG = 0x800000;  // PCIe5 - 23
    DBG_LSB_REG = 0x1000000;  // PCIe6 - 24
    DBG_LSB_REG = 0x2000000;  // PCIe7 - 25
    DBG_LSB_REG = 0x4000000;  // PCIe8 - 26
    DBG_LSB_REG = 0x8000000;  // PCIe9 - 27
    DBG_LSB_REG = 0x10000000;  // PCIe10 - 28
    DBG_LSB_REG = 0x20000000;  // PCIe11 - 29
    DBG_LSB_REG = 0x40000000;  // PCIe12 - 30
    DBG_LSB_REG = 0x80000000;  // PCIe13 - 31
    DBG_MSB_REG = 0x1;  // PCIe14 - 32
    DBG_MSB_REG = 0x2;  // PCIe15 - 33
    printf("--------------------------------------------------------------------------------------------------------------\r\n");
    
	val = PENDING_LSB_REG;
    printf("Interrupt test PENDING_LSB_REG = 0x%x !!\r\n", val);
	byte_read = read32(UART_BASE_ADDR);
	val = PENDING_LSB_REG;
    printf("Interrupt test PENDING_LSB_REG = 0x%x !!\r\n", val);

    while (val != 0x22);
    //while (byte_read != 0x30);
    
    printf("byte_read = 0x%x !!\r\n", byte_read);
    printf("Interrupt test finish!!\r\n");

    while(1);
}

void interrupt_plic_init(void) {

    /* Write mstatus.mie[3] = 0 to disable all machine interrupts prior to setup */
    csr_clr_bits_mstatus(MSTATUS_MIE_BIT_MASK);

    /* Disable External interrupts in mie register. */
    csr_clr_bits_mie(MIE_MEI_BIT_MASK);

    EL_LSB_REG =         0xFFFFFFFF;
    EL_MSB_REG =         0xFFFFFFFF;
    SM_LSB_REG =         0x00000000;
    SM_MSB_REG =         0x00000000;
    DBG_LSB_REG =        0x00000000;
    DBG_MSB_REG =        0x00000000;

    /* Setup PLIC based on interrupt lines in this design */
    IE_LSB_REG =         0xFFFFFFF8;
    IE_MSB_REG =         0xFFFFFFFF;

    /* Setup PLIC priority of interrupts */
    PRIORITY_0_REG  =   0x000000002;
    PRIORITY_1_REG  =   0x000000002;
    PRIORITY_2_REG  =   0x000000002;
    PRIORITY_3_REG  =   0x000000002;
    PRIORITY_4_REG  =   0x000000002;
    PRIORITY_5_REG  =   0x000000005;
    PRIORITY_6_REG  =   0x000000002;
    PRIORITY_7_REG  =   0x000000002;
    PRIORITY_8_REG  =   0x000000002;
    PRIORITY_9_REG  =   0x000000002;
    PRIORITY_10_REG =   0x000000002;
    PRIORITY_11_REG =   0x000000002;
    PRIORITY_12_REG =   0x000000002;
    PRIORITY_13_REG =   0x000000002;
    PRIORITY_14_REG =   0x000000002;
    PRIORITY_15_REG =   0x000000002;
    PRIORITY_16_REG =   0x000000002;
    PRIORITY_17_REG =   0x000000002;
    PRIORITY_18_REG =   0x000000002;
    PRIORITY_19_REG =   0x000000002;
    PRIORITY_20_REG =   0x000000002;
    PRIORITY_21_REG =   0x000000002;
    PRIORITY_22_REG =   0x000000002;
    PRIORITY_23_REG =   0x000000002;
    PRIORITY_24_REG =   0x000000002;
    PRIORITY_25_REG =   0x000000002;
    PRIORITY_26_REG =   0x000000002;
    PRIORITY_27_REG =   0x000000002;
    PRIORITY_28_REG =   0x000000002;
    PRIORITY_29_REG =   0x000000002;
    PRIORITY_30_REG =   0x000000002;
    PRIORITY_31_REG =   0x000000002;
    PRIORITY_32_REG =   0x000000002;
    PRIORITY_33_REG =   0x000000002;

    /* Set global threshold register to 01 to allow all interrupts of priority of 2 and above */
    THRESHOLD_0_REG  =  0x000000001; 
    THRESHOLD_1_REG  =  0x000000001;
    THRESHOLD_2_REG  =  0x000000001;
    THRESHOLD_3_REG  =  0x000000001;
    THRESHOLD_4_REG  =  0x000000001;
    THRESHOLD_5_REG  =  0x000000001;
    THRESHOLD_6_REG  =  0x000000001;
    THRESHOLD_7_REG  =  0x000000001;
    THRESHOLD_8_REG  =  0x000000001;
    THRESHOLD_9_REG  =  0x000000001;
    THRESHOLD_10_REG =  0x000000001;
    THRESHOLD_11_REG =  0x000000001;
    THRESHOLD_12_REG =  0x000000001;
    THRESHOLD_13_REG =  0x000000001;
    THRESHOLD_14_REG =  0x000000001;
    THRESHOLD_15_REG =  0x000000001;
    THRESHOLD_16_REG =  0x000000001;
    THRESHOLD_17_REG =  0x000000001;
    THRESHOLD_18_REG =  0x000000001;
    THRESHOLD_19_REG =  0x000000001;
    THRESHOLD_20_REG =  0x000000001;
    THRESHOLD_21_REG =  0x000000001;
    THRESHOLD_22_REG =  0x000000001;
    THRESHOLD_23_REG =  0x000000001;
    THRESHOLD_24_REG =  0x000000001;
    THRESHOLD_25_REG =  0x000000001;
    THRESHOLD_26_REG =  0x000000001;
    THRESHOLD_27_REG =  0x000000001;
    THRESHOLD_28_REG =  0x000000001;
    THRESHOLD_29_REG =  0x000000001;
    THRESHOLD_30_REG =  0x000000001;
    THRESHOLD_31_REG =  0x000000001;
    THRESHOLD_32_REG =  0x000000001;
    THRESHOLD_33_REG =  0x000000001;

    /* Enable External interrupts in mie register. */
    csr_set_bits_mie(MIE_MEI_BIT_MASK);

    /* Write mstatus.mie = 1 to enable all machine interrupts */
    csr_set_bits_mstatus(MSTATUS_MIE_BIT_MASK);

}

